<template>
    <section :class="['code-content', sizeClass]">
        <section class="copy-code" @click="copyCode">
            <Icon icon="icon-fuzhi-" />
        </section>
        <span class="lang">{{ props.lang }}</span>
        <section v-html="shikiCode"></section>
    </section>
</template>

<script setup>
import { codeToHtml } from "shiki";
import {
    defineAsyncComponent,
    markRaw,
    shallowRef,
    ref,
    onMounted,
    watch,
    computed,
} from "vue";

const shikiCode = ref("");
const props = defineProps({
    code: {
        type: String,
        default: () => "",
    },
    lang: {
        type: String,
        default: () => "vue",
    },
    size: {
        type: String,
        default: () => "normal",
    },
});

const sizeClass = computed(() => {
    return new Map([
        ["normal", "normal"],
        ["large", "large"],
    ]).get(props.size);
});

const renderPropsCode = async (code) => {
    shikiCode.value = await codeToHtml(decodeURIComponent(code), {
        lang: props.lang,
        theme: "vitesse-dark",
    });
};

const copyCode = () => {
    navigator.clipboard
        .writeText(decodeURIComponent(props.code))
        .then(() => {
            ElMessage({
                message: "design: 代码复制成功！",
                type: "success",
            });
        })
        .catch((e) => {
            ElMessage({
                message: "design: 代码复制失败！" + e.message || e,
                type: "error",
            });
        });
};

watch(
    props,
    ({ code }) => {
        if (!code?.trim?.()) return;
        renderPropsCode(code.trimStart());
    },
    { immediate: true },
);

defineExpose({
    copyCode,
});
</script>

<style scoped lang="less">
.code-content {
    position: relative;

    .lang {
        position: absolute;
        top: @small-space * 2;
        right: @small-space * 2.5;
        font-size: 0.9rem;
        letter-spacing: 0.5px;
        color: rgba(219, 215, 202, 0.933);
    }

    .copy-code {
        display: none;
        position: absolute;
        background-color: #f6f6f7;
        border-radius: 3px;
        right: @small-space * 2.5;
        top: @small-space * 2;
        padding: @small-space;
        cursor: pointer;
        font-weight: bold;
    }
    &:hover {
        .lang {
            display: none;
        }
        .copy-code {
            display: block !important;
        }
    }
}

.normal {
    border-radius: 10px;

    /deep/ .vitesse-dark {
        padding: 18px 10px;
        box-sizing: border-box;
        font-size: 0.9rem;
        border-radius: 6px;
    }
}

.large {
    /deep/ .vitesse-dark {
        padding: 20px 10px;
        box-sizing: border-box;

        .line {
            line-height: 30px;
        }
    }
}
</style>
